package ci.model;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;




public class Tester1 {

	
	static HashMap<String, HashMap<String, Double>> critics = 
		new HashMap<String, HashMap<String,Double>>();
	

	static {
	
		HashMap<String, Double> lisaRosesMovies = new HashMap<String, Double>();
		lisaRosesMovies.put("Lady in the Water", 2.5D);
		lisaRosesMovies.put("Snakes on a Plane", 3.5D);
		lisaRosesMovies.put("Just My Luck", 3.0D);
		lisaRosesMovies.put("Superman Returns", 3.5D);
		lisaRosesMovies.put("You, Me and Dupree", 2.5D);
		lisaRosesMovies.put("The Night Listener", 3.0D);
		
		critics.put("Lisa Rose", lisaRosesMovies);		
		
		HashMap<String, Double> genySeymourMovies = new HashMap<String, Double>();
		genySeymourMovies.put("Lady in the Water", 3.0D);
		genySeymourMovies.put("Snakes on a Plane", 3.5D);
		genySeymourMovies.put("Just My Luck", 1.5D);
		genySeymourMovies.put("Superman Returns", 5.0D);
		genySeymourMovies.put("The Night Listener", 3.0D);
		genySeymourMovies.put("You, Me and Dupree", 3.5D);
		
		critics.put("Gene Seymour", genySeymourMovies);
		
		HashMap<String, Double> michaelsPhillips = new HashMap<String, Double>();
		michaelsPhillips.put("Lady in the Water", 2.5D);
		michaelsPhillips.put("Snakes on a Plane", 3.0D);
		michaelsPhillips.put("Superman Returns", 3.5D);
		michaelsPhillips.put("The Night Listener", 4.0D);
		
		critics.put("Michaels Phillips", michaelsPhillips);
		
		HashMap<String, Double> claudiaPuig = new HashMap<String, Double>();
		claudiaPuig.put("Snakes on a Plane", 3.5D);
		claudiaPuig.put("Just My Luck", 3.0D);
		claudiaPuig.put("The Night Listener", 4.5D);
		claudiaPuig.put("Superman Returns", 4.0D);
		claudiaPuig.put("You, Me and Dupree", 2.5D);
		
		critics.put("Claudia Puig", claudiaPuig);
		
		HashMap<String, Double> mickLaSalle = new HashMap<String, Double>();
		mickLaSalle.put("Lady in the Water", 3.0D);
		mickLaSalle.put("Snakes on a Plane", 4.0D);
		mickLaSalle.put("Just My Luck", 2.0D);
		mickLaSalle.put("Superman Returns", 3.0D);
		mickLaSalle.put("The Night Listener", 3.0D);
		mickLaSalle.put("You, Me and Dupree", 2.0D);
		
		critics.put("Mick LaSalle", mickLaSalle);
		
		HashMap<String, Double>	jackMatthews = new HashMap<String, Double>();
		jackMatthews.put("Lady in the Water", 3.0D);
		jackMatthews.put("Snakes on a Plane", 4.0D);
		jackMatthews.put("The Night Listener", 3.0D);
		jackMatthews.put("Superman Returns", 5.0);
		jackMatthews.put("You, Me and Dupree", 3.5D);
		
		critics.put("Jack Matthews", jackMatthews);
		
		HashMap<String, Double> toby = new HashMap<String, Double>();
		toby.put("Snakes on a Plane", 4.5D);
		toby.put("You, Me and Dupree", 1.0D);
		toby.put("Superman Returns", 4.0D);
		
		critics.put("Toby", toby);
	}
	
	
	private static Double simDistance(
				HashMap<String, HashMap<String, Double>> prefs, 
				String person1, String person2) throws Exception {
		
		HashMap<String, Integer> si = new HashMap<String, Integer>();
		
		Double sumOfSquares = 0D;
		
		// las peliculas del primer critico
		HashMap<String, Double> moviesByCritic1 = prefs.get(person1);		
		
		// las peliculas del segundo critico
		HashMap<String, Double> moviesByCritic2 = prefs.get(person2);			
					
		Iterator<Entry<String, Double>> iteratorCritic1 = 
			moviesByCritic1.entrySet().iterator();				
		
		while(iteratorCritic1.hasNext()) {			
			
			Map.Entry<String, Double> nextMovie = 
				(Map.Entry<String, Double>)iteratorCritic1.next();			
			
			if( moviesByCritic2.containsKey(nextMovie.getKey()) ) {
							
				Double movieRatingCritic1 =  nextMovie.getValue();
				Double movieRatingCritic2 =  moviesByCritic2.get(nextMovie.getKey());
				
				sumOfSquares += Math.pow((movieRatingCritic1-movieRatingCritic2), 2.0);				

				// sirve de validacion
				si.put(nextMovie.getKey(), 1);						
			}		
			
		}// end while
		
		if(si.size() == 0) {
			return 0D;
		}
				
		
		return 1/(1+sumOfSquares);		
	}
	
	
	private static Double simPearson(HashMap<String, HashMap<String, Double>> prefs, 
			String person1, String person2) throws Exception {		
		
		HashMap<String, Integer> si = new HashMap<String, Integer>();
		
		Double r = 0D;
		
		// las peliculas del primer critico
		HashMap<String, Double> moviesByCritic1 = prefs.get(person1);		
					
		// las peliculas del segundo critico
		HashMap<String, Double> moviesByCritic2 = prefs.get(person2);		
							
		Iterator<Entry<String, Double>> iteratorCritic1 = 
			moviesByCritic1.entrySet().iterator();				
		
		while(iteratorCritic1.hasNext()) {			
			
			Map.Entry<String, Double> nextMovie = 
				(Map.Entry<String, Double>)iteratorCritic1.next();			
			
			if( moviesByCritic2.containsKey(nextMovie.getKey()) ) {										
				// sirve de validacion
				si.put(nextMovie.getKey(), 1);						
			}			
			
		}// end while				
			
		if(si.size() == 0) {
			return 0D;
		}
		
		int n = si.size();
		
		double sum1 = 0, sum2 = 0;
		
		iteratorCritic1 = moviesByCritic1.entrySet().iterator();
		
		// Sums of all the preferences
		while(iteratorCritic1.hasNext()) {			
			
			Map.Entry<String, Double> nextMovie = 
				(Map.Entry<String, Double>)iteratorCritic1.next();			
			
			if( moviesByCritic2.containsKey(nextMovie.getKey()) ) {										
				sum1+=nextMovie.getValue();
				sum2+=moviesByCritic2.get(nextMovie.getKey());
			}			
			
		}// end while		
		
		double sum1Sq = 0, sum2Sq = 0;
		
		iteratorCritic1 = moviesByCritic1.entrySet().iterator();
		
		// Sums of the squares
		while(iteratorCritic1.hasNext()) {			
			
			Map.Entry<String, Double> nextMovie = 
				(Map.Entry<String, Double>)iteratorCritic1.next();			
			
			if( moviesByCritic2.containsKey(nextMovie.getKey()) ) {										
				sum1Sq+=Math.pow(nextMovie.getValue(), 2);
				sum2Sq+=Math.pow(moviesByCritic2.get(nextMovie.getKey()), 2);
			}			
			
		}// end while
		
		
		double pSum = 0;
		
		iteratorCritic1 = moviesByCritic1.entrySet().iterator();
		
		// Sums of the products
		while(iteratorCritic1.hasNext()) {			
			
			Map.Entry<String, Double> nextMovie = 
				(Map.Entry<String, Double>)iteratorCritic1.next();			
			
			if( moviesByCritic2.containsKey(nextMovie.getKey()) ) {										
				Double movieRatingCritic1 =  nextMovie.getValue();
				Double movieRatingCritic2 =  moviesByCritic2.get(nextMovie.getKey());
				
				pSum += (movieRatingCritic1*movieRatingCritic2);
			}			
			
		}// end while
		
		
		 // Calculate r (Pearson score)
		  double num=pSum-(sum1*sum2/n);
		  double den=Math.sqrt((sum1Sq-Math.pow(sum1,2)/n)*(sum2Sq-Math.pow(sum2,2)/n));
		  
		  if(den == 0) {
			  return 0D;
		  }
		  
		r = num/den;
		  
		return r;	
	}
	
	
	public static void main(String[] args) {		
		
		try {
			System.out.println("Los criticos son: Lisa Rose y Gene Seymour");
			Double simDistance = Tester1.simDistance(critics, "Lisa Rose", "Gene Seymour");
			
			System.out.println("La distancia euclidiana es: "+simDistance);
			
			System.out.println("\nLos criticos son: Gene Seymour y Toby");
			Double simPearson = Tester1.simPearson(critics, "Lisa Rose", "Gene Seymour");
			
			System.out.println("La correlacion de pearson es: "+simPearson);
		}catch(Exception e) {
			e.printStackTrace();
		}
		
		
	}
	
}
